/**
 * DateUtils.java
 * Created at 2016年3月15日
 * Created by Jackie Liu
 * Copyright (C) 2016 Xin Hua Bo, All rights reserved.
 */
package com.huabo.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;

/**
 * <p>ClassName: DateUtils</p>
 * <p>Description: 日期出来工具类</p>
 * <p>Author: Jackie Liu</p>
 * <p>Date: 2016年3月15日</p>
 */
public class DateUtils {
	/**
     * 日期格式："yyyy-MM-dd"
     */
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    /**
     * 日期格式："yyyy年MM月dd日"
     */
    public static final String DATE_PATTERN_CN = "yyyy年MM月dd日";
    /**
     * 日期时间格式："yyyy-MM-dd HH:mm:ss"
     */
    public static final String DATE_TIME_PATTERN = "yyyy-MM-dd HH:mm:ss";
    
    private static String[] parsePatterns = {
    		"yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", 
    		"yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
    		"yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    /**
     * "yyyy-MM-dd"格式的SimpleDateFormat对象
     */
    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat(DATE_PATTERN);
    public static final SimpleDateFormat DATE_FORMAT_CN = new SimpleDateFormat(DATE_PATTERN_CN);
    /**
     * "yyyy-MM-dd HH:mm:ss"格式的SimpleDateFormat对象
     */
    public static final SimpleDateFormat DATE_TIME_FORMAT = new SimpleDateFormat(DATE_TIME_PATTERN);
    
    private static final Calendar CALENDAR = Calendar.getInstance();
    
    private static final long ONE_MINUTE = 60000L;
    private static final long ONE_HOUR = 3600000L;
    private static final long ONE_DAY = 86400000L;
    //private static final long ONE_WEEK = 604800000L;

    /*private static final String ONE_SECOND_AGO = "秒前";
    private static final String ONE_MINUTE_AGO = "分钟前";
    private static final String ONE_HOUR_AGO = "小时前";
    private static final String ONE_DAY_AGO = "天前";
    private static final String ONE_MONTH_AGO = "月前";
    private static final String ONE_YEAR_AGO = "年前";*/
    
    /**
     * 返回一个格式为yyyy-MM-dd HH:mm:ss精确到分的日期字符串
     * @param date
     * @return String
     */
    public static String dateTimeToString(Date date) {
        return DATE_TIME_FORMAT.format(date);
    }
    
    /**
     * 返回一个yyyy-MM-dd格式的日期字符串
     * @param date Date对象
     * @return String
     */
    public static String dateToString(Date date){
        return DATE_FORMAT.format(date);
    }
    
    /**
     * 返回一个yyyy年MM月dd日格式的日期字符串
     * @param date Date对象
     * @return String
     */
    public static String dateToCNString(Date date){
        return DATE_FORMAT_CN.format(date);
    }
    
    /**
     * 获取一个yyyy-MM-dd格式的系统当前日期
     * @return
     */
    public static String getNowTime() {
        return new SimpleDateFormat(DATE_PATTERN).format(new Date());
    }
    
    /**
     * <p>Description: 获取系统当前时间(指定返回类型)</p>
     * @param pattern 日期格式
     * @return
     */
    public static String getNowTime(String pattern) {
        return new SimpleDateFormat(pattern).format(new Date());
    }
    
    /**
     * <p>Description: 返回一个自定义格式的日期字符串</p>
     * @param date Date对象
     * @param pattern 日期格式
     * @return
     */
    public static String dateToString(Date date, String pattern){
        return new SimpleDateFormat(pattern).format(date);
    }
    
    /**
     * <p>Description: 把格式化的日期字符串转化成Date对象</p>
     * @param dateStr 日期字符串
     * @param pattern 日期格式
     * @return
     */
    public static Date stringToDate(String dateStr, String pattern){
        Date newDate = null;
        try {
            newDate = new SimpleDateFormat(pattern).parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return newDate;
    }
    
    /**
     * <p>
     * Description: 把如下格式的字符串转换成日期对象<br/>
     * "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", <br/>
     * "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",<br/>
     * "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"
     * </p>
     * @param dateStr 日期字符串
     * @return
     */
    public static Date stringToDate2(String dateStr){
        Date newDate = null;
        try {
			newDate = org.apache.commons.lang3.time.DateUtils.parseDate(dateStr, parsePatterns);
		} catch (ParseException e) {
			e.printStackTrace();
		}
        return newDate;
    }
    
    /**
     * <p>Description: 把"yyyy-MM-dd"格式的日期字符串转化成Date对象</p>
     * @param dateStr 日期字符串
     * @return
     */
    public static Date stringToDate(String dateStr){
        Date newDate = null;
        try {
            newDate = DATE_FORMAT.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return newDate;
    }
    
    /**
     * <p>Description: 把"yyyy-MM-dd HH:mm:ss"格式的日期字符串转化成Date对象</p>
     * @param dateStr 日期字符串
     * @return
     */
    public static Date stringTimeToDate(String dateStr){
        Date newDate = null;
        try {
            newDate = DATE_TIME_FORMAT.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return newDate;
    }
    
    /**
     * 返回两个日期之间相差的天数
     * @param begin 格式为yyyy-MM-dd
     * @param end 格式为yyyy-MM-dd
     * @return int
     */
    public static int countDays(String begin, String end){
        int days = 0;
        Calendar c_b = Calendar.getInstance();
        Calendar c_e = Calendar.getInstance();
        try{
            c_b.setTime(DATE_FORMAT.parse(begin));
            c_e.setTime(DATE_FORMAT.parse(end));
       
            while(c_b.before(c_e)){
                days++;
                c_b.add(Calendar.DAY_OF_YEAR, 1);
            }
        }catch(ParseException pe){
            System.out.println("日期格式必须为：yyyy-MM-dd；如：2010-04-04.");
            pe.printStackTrace();
        }
        return days; 
    } 
    
    /**
     * 返回两个日期之间相差的天数
     * @param begin
     * @param end
     * @return int
     */
    public static int countDays(Date begin, Date end){
        int days = 0;
        Calendar c_b = Calendar.getInstance();
        Calendar c_e = Calendar.getInstance();
        c_b.setTime(begin);
        c_e.setTime(end);
   
        while(c_b.before(c_e)){
            days++;
            c_b.add(Calendar.DAY_OF_YEAR, 1);
        }
        return days; 
    } 
    
    /**
     * 判断2个时间相差多少天、多少小时、多少分<br>
     * <br>
     * @param begin 开始时间，格式：yyyy-MM-dd hh:mm<br>
     * @param end 结束时间，格式：yyyy-MM-dd hh:mm<br>
     * @return String 计算结果<br>
     * @Exception 发生异常<br>
     */
	 public static String timeDiffFormat(String begin, String end) throws Exception {
		  SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm");
		  Long beginL = format.parse(begin).getTime();
		  Long endL = format.parse(end).getTime();
		  Long day = (endL - beginL)/86400000;
		  Long hour = ((endL - beginL)%86400000)/3600000;
		  Long min = ((endL - beginL)%86400000%3600000)/60000;
		  return (day + "天" + hour + "小时" + min + "分钟");
	 }
	 
	/**
     * 判断2个时间相差多少分<br>
     * <br>
     * @param begin 开始时间，格式：yyyy-MM-dd hh:mm<br>
     * @param end 结束时间，格式：yyyy-MM-dd hh:mm<br>
     * @return long 计算结果<br>
     */
	 public static long timeDiff(String begin, String end) {
		 long min = -1;
		 try {
			 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm");
			 Long beginL = format.parse(begin).getTime();
			 Long endL = format.parse(end).getTime();
			 min = (endL - beginL)/60000;
		 } catch (ParseException e) {
			 e.printStackTrace();
		 }
		 return min;
	 }
	 
	 /**
	  * 判断2个时间相差多少分<br>
	  * <br>
	  * @param begin 开始时间<br>
	  * @param end 结束时间<br>
	  * @return long 计算结果<br>
	  */
	 public static long timeDiff(Date begin, Date end) {
		 return (end.getTime() - begin.getTime())/60000;
	 }
 
    /**
     * 判断date1是否大于date2
     * @param date1 日期，格式为yyyy-MM-dd
     * @param date2 日期，格式为yyyy-MM-dd
     * @return
     */
    public static boolean compareDateStr(String date1, String date2) {
    	Date d1 = stringToDate(date1, DATE_PATTERN);
    	Date d2 = stringToDate(date2, DATE_PATTERN);
    	int flag = d1.compareTo(d2);
    	if (flag <= 0) {
    		return false; 
		}
    	return true;
    }
    
    /**
     * 判断date1是否大于date2
     * @param date1 Date对象
     * @param date2 Date对象
     * @return
     */
    public static boolean compareDate(Date date1, Date date2) {
    	int flag = date1.compareTo(date2);
    	if (flag <= 0) {
    		return false; 
		}
    	return true;
    }
    
    /**
     * 判断date1是否大于等于date2
     * @param date1 Date对象
     * @param date2 Date对象
     * @return
     */
    public static boolean compareDateWidthEqual(Date date1, Date date2) {
    	int flag = date1.compareTo(date2);
    	if (flag < 0) {
    		return false; 
		}
    	return true;
    }
    
    /**
     * 给指定的日期加上(减去)月份
     * @param date Date对象
     * @param pattern 日期格式类型
     * @param num 月份数
     * @return
     */
    public static String addMoth(Date date, String pattern, int num){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.add(Calendar.MONTH, num);
        return simpleDateFormat.format(calender.getTime());
    }


    /**
     * 给指定的时间加上(减去)天
     * @param date Date对象
     * @param pattern 日期格式类型
     * @param num 天数
     * @return
     */
    public static String addDay(Date date, String pattern, int num){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.add(Calendar.DATE, num);
        return simpleDateFormat.format(calender.getTime());
    }
    
    /**
     * 给指定的时间加上(减去)天
     * @param date Date对象
     * @param num 天数
     * @return
     */
    public static Date addDay(Date date, int num){
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.add(Calendar.DATE, num);
        return calender.getTime();
    }
    
    /**
     * 给指定的时间加上(减去)小时
     * @param date Date对象
     * @param pattern 日期格式类型
     * @param num 小时
     * @return
     */
    public static String addHour(Date date, String pattern, int num){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.add(Calendar.HOUR, num);
        return simpleDateFormat.format(calender.getTime());
    }
    
    /**
     * 给指定的时间加上(减去)小时
     * @param date Date对象
     * @param num 小时
     * @return
     */
    public static Date addHour(Date date, int num){
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.add(Calendar.HOUR, num);
        return calender.getTime();
    }
    
    /**
     * 给指定的时间加上(减去)分钟
     * @param date Date对象
     * @param pattern 日期格式类型
     * @param num 分钟
     * @return
     */
    public static String addMinute(Date date, String pattern, int num){
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.add(Calendar.MINUTE, num);
        return simpleDateFormat.format(calender.getTime());
    }
    
    /**
     * 给指定的时间加上(减去)分钟
     * @param date Date对象
     * @param num 分钟
     * @return
     */
    public static Date addMinute(Date date, int num){
        Calendar calender = Calendar.getInstance();
        calender.setTime(date);
        calender.add(Calendar.MINUTE, num);
        return calender.getTime();
    }
    
    /**
     * 将指定的日期转换成Unix时间戳
     * @param date 需要转换的日期 yyyy-MM-dd HH:mm:ss
     * @return long 时间戳
     */
    public static long dateToUnixTimestamp(String date) {
        long timestamp = 0;
        try {
            timestamp = new SimpleDateFormat(DATE_TIME_PATTERN).parse(date).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        
        return timestamp;
    }
    
    /**
     * 将指定的日期转换成Unix时间戳
     * @param  date 需要转换的日期 yyyy-MM-dd
     * @return long 时间戳
     */
    public static long dateToUnixTimestamp(String date, String pattern) {
        long timestamp = 0;
        try {
            timestamp = new SimpleDateFormat(pattern).parse(date).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return timestamp;
    }
    
    /**
     * 将当前日期转换成Unix时间戳
     * @return long 时间戳
     */
    public static long dateToUnixTimestamp() {
        return System.currentTimeMillis();
    }

    /**
     * 将Unix时间戳转换成日期
     * @param timestamp 时间戳
     * @return String 日期字符串
     */
    public static String unixTimestampToDate(long timestamp) {
        SimpleDateFormat sd = new SimpleDateFormat(DATE_TIME_PATTERN);
        sd.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        return sd.format(new Date(timestamp));
    }

    /**
     * 将Unix时间戳转换成日期
     * @param timestamp 时间戳
     * @return String 日期字符串
     */
    public static String timeStamp2Date(long timestamp, String pattern){
        String date = new SimpleDateFormat(pattern).format(new Date(timestamp));
        return date;
    }

    /**
     * 将Unix时间戳转换成日期
     * @param timestamp 时间戳
     * @return String 日期字符串
     */
    public static String timeStamp2Date(long timestamp){
        String date = new SimpleDateFormat(DATE_TIME_PATTERN).format(new Date(timestamp));
        return date;
    }
    
    /**
     * <p>Description: 将时间戳转换为自定义格式的日期字符串</p>
     * @param timestamp 时间戳
     * @param pattern 日期格式
     * @return
     */
    public static String timeMillisToString(long timestamp, String pattern) {
    	Calendar calendar = Calendar.getInstance();
    	calendar.setTimeInMillis(timestamp);
    	
    	SimpleDateFormat simpleDateFormat = new SimpleDateFormat(pattern);
    	return simpleDateFormat.format(calendar.getTime());
    }
    
    /** 
     * 判断当前日期是星期几<br> 
     * <br> 
     * @param pTime 修要判断的时间<br> 
     * @return dayForWeek 判断结果<br> 
     * @Exception 发生异常<br> 
     */  
	public static int dayForWeek(String pTime){
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");  
		Calendar c = Calendar.getInstance();  
		try{
			c.setTime(format.parse(pTime));
		}catch(Exception e){
			return 0;
		}
		int dayForWeek = 0;
		if(c.get(Calendar.DAY_OF_WEEK) == 1){  
			dayForWeek = 7;  
		}else{
			dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;  
		}
		return dayForWeek;
	}
	
    /** 
     * 判断当前日期是星期几<br> 
     * <br> 
     * @param pTime 修要判断的时间<br> 
     * @return dayForWeek 判断结果<br> 
     * @Exception 发生异常<br> 
     */  
	public static int dayForWeek(Date pTime){
		Calendar c = Calendar.getInstance();  
		c.setTime(pTime);
		int dayForWeek = 0;
		if(c.get(Calendar.DAY_OF_WEEK) == 1){  
			dayForWeek = 7;  
		}else{
			dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;  
		}
		return dayForWeek;
	}
	
	/**
	 * <p>Description: 获取某日期在所在年是第几周</p>
	 * @param date Date对象
	 * @return 周数
	 */
    public static int getWeekOfYear(Date date) {
        //Calendar CALENDAR = new GregorianCalendar();
    	CALENDAR.setFirstDayOfWeek(Calendar.MONDAY);
    	CALENDAR.setMinimalDaysInFirstWeek(7);
    	CALENDAR.setTime(date);
 
        return CALENDAR.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 获取某月总共有多少天
     * @param date Date对象
     * @return 周数
     */
    public static int getDaysOfMonth(Date date) {
        //Calendar CALENDAR = new GregorianCalendar();
        //CALENDAR.setFirstDayOfWeek(Calendar.MONDAY);
        //CALENDAR.setMinimalDaysInFirstWeek(7);
        CALENDAR.setTime(date);

        return CALENDAR.getActualMaximum(Calendar.DATE);
    }
 
    /**
     * <p>Description: 获取某年的总共周数</p>
     * @param year 年份(如：2016)
     * @return 周数
     */
    public static int getMaxWeekNumOfYear(int year) {
        //Calendar CALENDAR = new GregorianCalendar();
    	CALENDAR.set(year, Calendar.DECEMBER, 31, 23, 59, 59);
 
        return getWeekOfYear(CALENDAR.getTime());
    }
 
    /**
     * <p>Description: 获取某年的第几周的开始日期</p>
     * @param year 年份(如：2016)
     * @param week 周数(如：36)
     * @return
     */
    public static Date getFirstDayOfWeek(int year, int week) {
        //Calendar CALENDAR = new GregorianCalendar();
    	CALENDAR.set(Calendar.YEAR, year);
        CALENDAR.set(Calendar.MONTH, Calendar.JANUARY);
        CALENDAR.set(Calendar.DATE, 1);
 
        Calendar cal = (GregorianCalendar) CALENDAR.clone();
        cal.add(Calendar.DATE, week * 7);
 
        return getFirstDayOfWeek(cal.getTime());
    }
 
    /**
     * <p>Description: 获取某年的第几周的结束日期</p>
     * @param year 年份(如：2016)
     * @param week 周数(如：36)
     * @return
     */
    public static Date getLastDayOfWeek(int year, int week) {
        //Calendar CALENDAR = new GregorianCalendar();
    	CALENDAR.set(Calendar.YEAR, year);
        CALENDAR.set(Calendar.MONTH, Calendar.JANUARY);
        CALENDAR.set(Calendar.DATE, 1);
 
        Calendar cal = (GregorianCalendar) CALENDAR.clone();
        cal.add(Calendar.DATE, week * 7);
 
        return getLastDayOfWeek(cal.getTime());
    }
 
    /**
     * <p>Description: 获取某日期所在周的开始日期</p>
     * @param date Date对象
     * @return
     */
    public static Date getFirstDayOfWeek(Date date) {
        //Calendar CALENDAR = new GregorianCalendar();
        CALENDAR.setFirstDayOfWeek(Calendar.MONDAY);
        CALENDAR.setTime(date);
        CALENDAR.set(Calendar.DAY_OF_WEEK, CALENDAR.getFirstDayOfWeek()); // Monday
        return CALENDAR.getTime();
    }
 
    /**
     * <p>Description: 获取当前时间所在周的结束日期</p>
     * @param date Date对象
     * @return
     */
    public static Date getLastDayOfWeek(Date date) {
        //Calendar CALENDAR = new GregorianCalendar();
        CALENDAR.setFirstDayOfWeek(Calendar.MONDAY);
        CALENDAR.setTime(date);
        CALENDAR.set(Calendar.DAY_OF_WEEK, CALENDAR.getFirstDayOfWeek() + 6); // Sunday
        return CALENDAR.getTime();
    }
    
	/**
	 * <p>Description: 日期格式化，如几天前、几分钟前，30天之后的日期按pattern格式</p>
	 * @param date 需要格式化的日期实例
	 * @param pattern 默认日期格式化的格式
	 * @return 格式化后的日期
	 */
	public static String format(Date date, String pattern) {
        long delta = System.currentTimeMillis() - date.getTime();
        /*if (delta < 1L * ONE_MINUTE) {
            long seconds = toSeconds(delta);
            return (seconds <= 0 ? 1 : seconds) + "秒前";
        }*/
        if (delta < 45L * ONE_MINUTE) {
            long minutes = toMinutes(delta);
            return (minutes <= 0 ? 1 : minutes) + "分钟前";
        }
        if (delta < 24L * ONE_HOUR) {
            long hours = toHours(delta);
            return (hours <= 0 ? 1 : hours) + "小时前";
        }
        if (delta < 48L * ONE_HOUR) {
            return "昨天";
        }
        if (delta < 30L * ONE_DAY) {
            long days = toDays(delta);
            return (days <= 0 ? 1 : days) + "天前";
        }
        /*if (delta < 12L * 4L * ONE_WEEK) {
            long months = toMonths(delta);
            return (months <= 0 ? 1 : months) + "月前";
        } else {
            long years = toYears(delta);
            return (years <= 0 ? 1 : years) + "年前";
        }*/
        return dateToString(date, pattern);
    }
	
	private static long toSeconds(long date) {  
        return date / 1000L;  
    }  
  
    private static long toMinutes(long date) {  
        return toSeconds(date) / 60L;  
    }  
  
    private static long toHours(long date) {  
        return toMinutes(date) / 60L;  
    }  
  
    private static long toDays(long date) {  
        return toHours(date) / 24L;  
    }  
  
    /*private static long toMonths(long date) {  
        return toDays(date) / 30L;  
    }  
  
    private static long toYears(long date) {  
        return toMonths(date) / 365L;  
    }*/
    
    public static void main(String[] args) {
    	//Date begin = stringTimeToDate("2016-11-01");
    	//Date end = stringTimeToDate("2016-11-01");
        /*Date date = null;
        try {
            date = new SimpleDateFormat("yyyy-MM-dd").parse("2016-02-01");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        System.out.println(DateUtils.getDaysOfMonth(date));*/
        System.out.println(getNowTime("dd"));
    }
}
